package com.ygqh.baby.controller.os;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;

import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.io.IOUtils;
import org.apache.log4j.spi.LoggerFactory;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import com.alibaba.fastjson.JSON;
import com.ygqh.baby.ao.OrderDetailStatus;
import com.ygqh.baby.ao.RefundStatus;
import com.ygqh.baby.controller.mobile.BaseController;
import com.ygqh.baby.model.OrderDeliverModel;
import com.ygqh.baby.po.YgLogistics;
import com.ygqh.baby.po.YgOrderDetail;
import com.ygqh.baby.po.YgReturnOrderDetail;
import com.ygqh.baby.service.OrderSendHandler;
import com.ygqh.baby.service.YgLogisticsService;
import com.ygqh.baby.service.YgOrderDetailService;
import com.ygqh.baby.service.YgOrderService;
import com.ygqh.baby.service.YgReturnOrderDetailService;
import com.ygqh.baby.service.YgUserService;
import com.ygqh.baby.service.trustone.model.ApiResult;
import com.ygqh.baby.service.trustone.model.TrustoneLogistic;
import com.ygqh.baby.utils.YgStringUtils;

@Controller
@RequestMapping("/os/trustone")
public class TrustoneLogisticCallback extends BaseController{

	private Logger logger = org.slf4j.LoggerFactory.getLogger(getClass());
	@Autowired
	private OrderSendHandler orderSendHandler;
	@Autowired
	private YgOrderDetailService ygOrderDetailService;
	@Autowired
	private YgReturnOrderDetailService ygReturnOrderDetailService;
	@Value("${trustoner.supplier.id}")
	private Long trustonerSupplierId;

	private final static ExecutorService executorService = Executors.newFixedThreadPool(3);

	@RequestMapping("logisticBack")
	public void trustoneLogisticCallback(HttpServletRequest request, HttpServletResponse response) throws Exception {
		
		TrustoneLogistic logistic = this.getLogisticByInputStream(request );
		if(logistic == null){
			logistic = this.getLogisticByParameterMap(request);
		}
		if(logistic== null){
			logger.info("保税仓物流回调：回调数据为空" );
		}else{
			this.doSend(logistic);
		}

		response.getWriter().write(JSON.toJSONString(new ApiResult(200, true, "")));

	}
	
	private TrustoneLogistic getLogisticByParameterMap(HttpServletRequest request){
		try {
			Map<String, String> map = this.getParameterMap(request.getParameterMap());
			if (map.isEmpty()) {
				return null;
			}
			logger.info("Trustone logisticBack by map: {}",JSON.toJSONString(map));
			TrustoneLogistic logistic = TrustoneLogistic.class.newInstance();
			BeanUtils.populate(logistic, map);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}
	
	private TrustoneLogistic getLogisticByInputStream(HttpServletRequest request){
		try {
			ServletInputStream inputStream = request.getInputStream();
			String res = IOUtils.toString(inputStream, "utf-8");
			logger.info("Trustone logisticBack by inputStream: {}",res);
			System.out.println(res);

			TrustoneLogistic logistic = JSON.parseObject(res, TrustoneLogistic.class);
			return logistic;
		} catch (IOException e) {
			e.printStackTrace();
		}
		return null;
	}
	

	private void doSend(TrustoneLogistic logistic) {
		executorService.execute(new Runnable() {
			public void run() {

				OrderDeliverModel deliverModel = buildOrderDeliverModels(logistic);

				if (deliverModel != null) {
					List<OrderDeliverModel> orderDeliverModels = new ArrayList<>();
					orderDeliverModels.add(deliverModel);
					orderSendHandler.send(orderDeliverModels);
				}
			}
		});
	}

	private OrderDeliverModel buildOrderDeliverModels(TrustoneLogistic logistic) {

		OrderDeliverModel deliverModel = new OrderDeliverModel();
		Date date = new Date();

		if (!YgStringUtils.isNum(logistic.getOrderUuid())) {
			deliverModel.setChange(true);
		}
		YgLogistics l = new YgLogistics();

		l.setOrderId(logistic.getOrderUuid());
		l.setExpressCompany(logistic.getLogisticName());
		l.setLogisticsCode(logistic.getLogisticCode());
		l.setExpressCode(logistic.getLogisticNo());
		l.setCreateTime(date);
		l.setSendTime(date);

		deliverModel.setYgLogistics(l);
		List<Long> detailIds = null;
		if (!deliverModel.isChange()) {

			List<YgOrderDetail> od = ygOrderDetailService.findByOrderId(Long.parseLong(l.getOrderId()));
			detailIds = od.stream().filter(d -> trustonerSupplierId.equals(d.getSupplierId()) && OrderDetailStatus.WaitingSend.equals(d.getDetailStatus())
					&& RefundStatus.NoRefund.equals(d.getRefundStatus())).map(d -> d.getId()).collect(Collectors.toList());

		} else {
			List<YgReturnOrderDetail> rod = ygReturnOrderDetailService.findByReturnCode(l.getOrderId());
			detailIds = rod.stream().filter(d -> trustonerSupplierId.equals(d.getSupplierId())).map(d -> d.getId()).collect(Collectors.toList());
		}
		deliverModel.setDetailIds(detailIds);
		return deliverModel;

	}

}
